"""
模板相关数据模型

包括模板基本信息和模板视频等模型。
"""

from datetime import datetime
from typing import Dict, Any, Optional, List
import json
import enum

from sqlalchemy import Column, Integer, String, Float, Text, Boolean, ForeignKey, Index, DateTime, Enum
from sqlalchemy.orm import relationship, backref

from .base import BaseModel, JSONField


class TemplateStatus(enum.Enum):
    """模板状态枚举"""
    DRAFT = "draft"              # 草稿
    ACTIVE = "active"            # 活跃
    INACTIVE = "inactive"        # 停用
    ARCHIVED = "archived"        # 归档


class TemplateType(enum.Enum):
    """模板类型枚举"""
    JIANYING = "jianying"        # 剪映模板
    PREMIERE = "premiere"        # Premiere模板
    AFTER_EFFECTS = "after_effects"  # After Effects模板
    CUSTOM = "custom"            # 自定义模板
    OTHER = "other"              # 其他


class Template(BaseModel):
    """
    模板表
    
    存储视频制作模板的基本信息。
    """
    
    __tablename__ = 'templates'
    
    # 基本信息
    name = Column(String(255), nullable=False, index=True)
    title = Column(String(500), nullable=True)
    description = Column(Text, nullable=True)
    
    # 模板标识
    template_id = Column(String(100), unique=True, nullable=False, index=True)  # 外部模板ID
    template_type = Column(Enum(TemplateType), nullable=False, default=TemplateType.OTHER)
    version = Column(String(50), nullable=True)
    
    # 状态信息
    status = Column(Enum(TemplateStatus), nullable=False, default=TemplateStatus.DRAFT)
    is_featured = Column(Boolean, default=False)
    is_premium = Column(Boolean, default=False)
    
    # 文件信息
    template_path = Column(String(500), nullable=True)      # 模板文件路径
    preview_image = Column(String(500), nullable=True)      # 预览图
    preview_video = Column(String(500), nullable=True)      # 预览视频
    
    # 技术规格
    canvas_width = Column(Integer, nullable=True)           # 画布宽度
    canvas_height = Column(Integer, nullable=True)          # 画布高度
    canvas_ratio = Column(String(20), nullable=True)        # 画布比例 (如 "16:9")
    duration = Column(Float, nullable=True)                 # 模板时长(秒)
    fps = Column(Float, nullable=True)                      # 帧率
    
    # 轨道信息
    video_tracks_count = Column(Integer, default=0)         # 视频轨道数
    audio_tracks_count = Column(Integer, default=0)         # 音频轨道数
    total_tracks_count = Column(Integer, default=0)         # 总轨道数
    
    # 素材需求
    required_video_count = Column(Integer, default=0)       # 需要的视频数量
    required_image_count = Column(Integer, default=0)       # 需要的图片数量
    required_audio_count = Column(Integer, default=0)       # 需要的音频数量
    
    # 分类和标签
    category = Column(String(100), nullable=True, index=True)
    subcategory = Column(String(100), nullable=True)
    tags = Column(JSONField, nullable=True)                 # 标签列表
    keywords = Column(Text, nullable=True)                  # 关键词
    
    # 设备信息 (从剪映模板提取)
    device_info = Column(JSONField, nullable=True)
    
    # 模板结构信息
    structure_info = Column(JSONField, nullable=True)       # 模板结构
    effects_info = Column(JSONField, nullable=True)         # 特效信息
    transitions_info = Column(JSONField, nullable=True)     # 转场信息
    
    # 使用统计
    usage_count = Column(Integer, default=0)                # 使用次数
    download_count = Column(Integer, default=0)             # 下载次数
    rating = Column(Float, nullable=True)                   # 评分 (1-5)
    rating_count = Column(Integer, default=0)               # 评分人数
    
    # 创作者信息
    author = Column(String(255), nullable=True)
    author_url = Column(String(500), nullable=True)
    license_type = Column(String(100), nullable=True)       # 许可类型
    
    # 兼容性信息
    min_app_version = Column(String(50), nullable=True)     # 最低应用版本
    supported_platforms = Column(JSONField, nullable=True)  # 支持的平台
    
    # 关联关系
    videos = relationship("TemplateVideo", back_populates="template", cascade="all, delete-orphan")
    output_materials = relationship("ProductOutputMaterial", back_populates="template")
    
    # 索引
    __table_args__ = (
        Index('idx_template_type_status', 'template_type', 'status'),
        Index('idx_template_category', 'category', 'subcategory'),
        Index('idx_template_canvas', 'canvas_width', 'canvas_height'),
        Index('idx_template_featured_premium', 'is_featured', 'is_premium'),
    )
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典格式"""
        result = super().to_dict()
        result['template_type'] = self.template_type.value if self.template_type else None
        result['status'] = self.status.value if self.status else None
        result['tags'] = self.get_tags()
        result['device_info'] = self.get_device_info()
        result['structure_info'] = self.get_structure_info()
        result['effects_info'] = self.get_effects_info()
        result['transitions_info'] = self.get_transitions_info()
        result['supported_platforms'] = self.get_supported_platforms()
        return result
    
    def get_tags(self) -> List[str]:
        """获取标签列表"""
        if self.tags:
            return json.loads(self.tags) if isinstance(self.tags, str) else self.tags
        return []
    
    def get_device_info(self) -> Dict[str, Any]:
        """获取设备信息"""
        if self.device_info:
            return json.loads(self.device_info) if isinstance(self.device_info, str) else self.device_info
        return {}
    
    def get_structure_info(self) -> Dict[str, Any]:
        """获取结构信息"""
        if self.structure_info:
            return json.loads(self.structure_info) if isinstance(self.structure_info, str) else self.structure_info
        return {}
    
    def get_effects_info(self) -> Dict[str, Any]:
        """获取特效信息"""
        if self.effects_info:
            return json.loads(self.effects_info) if isinstance(self.effects_info, str) else self.effects_info
        return {}
    
    def get_transitions_info(self) -> Dict[str, Any]:
        """获取转场信息"""
        if self.transitions_info:
            return json.loads(self.transitions_info) if isinstance(self.transitions_info, str) else self.transitions_info
        return {}
    
    def get_supported_platforms(self) -> List[str]:
        """获取支持的平台列表"""
        if self.supported_platforms:
            return json.loads(self.supported_platforms) if isinstance(self.supported_platforms, str) else self.supported_platforms
        return []
    
    def add_tag(self, tag: str):
        """添加标签"""
        tags = self.get_tags()
        if tag not in tags:
            tags.append(tag)
            self.tags = json.dumps(tags, ensure_ascii=False)
    
    def get_canvas_ratio_string(self) -> str:
        """获取画布比例字符串"""
        if self.canvas_ratio:
            return self.canvas_ratio
        elif self.canvas_width and self.canvas_height:
            # 计算最简比例
            from math import gcd
            g = gcd(self.canvas_width, self.canvas_height)
            return f"{self.canvas_width // g}:{self.canvas_height // g}"
        return "Unknown"
    
    def get_resolution_string(self) -> str:
        """获取分辨率字符串"""
        if self.canvas_width and self.canvas_height:
            return f"{self.canvas_width}x{self.canvas_height}"
        return "Unknown"
    
    def increment_usage(self):
        """增加使用次数"""
        self.usage_count += 1
    
    def increment_download(self):
        """增加下载次数"""
        self.download_count += 1
    
    def add_rating(self, rating: float):
        """添加评分"""
        if self.rating is None:
            self.rating = rating
            self.rating_count = 1
        else:
            total_rating = self.rating * self.rating_count + rating
            self.rating_count += 1
            self.rating = total_rating / self.rating_count
    
    def get_average_rating(self) -> float:
        """获取平均评分"""
        return self.rating or 0.0
    
    def is_popular(self) -> bool:
        """判断是否为热门模板"""
        return (self.usage_count >= 100 or 
                self.download_count >= 50 or 
                (self.rating and self.rating >= 4.0 and self.rating_count >= 10))
    
    def get_total_required_materials(self) -> int:
        """获取总共需要的素材数量"""
        return (self.required_video_count + 
                self.required_image_count + 
                self.required_audio_count)
    
    def __repr__(self):
        return f"<Template(id={self.id}, template_id='{self.template_id}', name='{self.name}', type='{self.template_type.value if self.template_type else None}')>"


class TemplateVideo(BaseModel):
    """
    模板视频表

    存储模板中的视频片段信息，用于素材替换。
    """

    __tablename__ = 'template_videos'

    # 关联模板
    template_id = Column(Integer, ForeignKey('templates.id'), nullable=False)
    template = relationship("Template", back_populates="videos")

    # 片段标识
    segment_id = Column(String(100), nullable=False)        # 片段ID
    segment_index = Column(Integer, nullable=False)         # 片段索引
    segment_name = Column(String(255), nullable=True)       # 片段名称

    # 轨道信息
    track_id = Column(String(100), nullable=True)           # 轨道ID
    track_index = Column(Integer, nullable=True)            # 轨道索引
    track_type = Column(String(50), nullable=True)          # 轨道类型

    # 时间信息
    start_time = Column(Float, nullable=False)              # 开始时间(秒)
    end_time = Column(Float, nullable=False)                # 结束时间(秒)
    duration = Column(Float, nullable=False)                # 时长(秒)

    # 源素材信息
    source_start = Column(Float, nullable=True)             # 源素材开始时间
    source_duration = Column(Float, nullable=True)          # 源素材时长

    # 原始素材信息
    original_material_id = Column(String(100), nullable=True)     # 原始素材ID
    original_material_name = Column(String(255), nullable=True)   # 原始素材名称
    original_material_path = Column(String(500), nullable=True)   # 原始素材路径

    # 素材要求
    required_width = Column(Integer, nullable=True)         # 要求宽度
    required_height = Column(Integer, nullable=True)        # 要求高度
    required_duration_min = Column(Float, nullable=True)    # 最小时长要求
    required_duration_max = Column(Float, nullable=True)    # 最大时长要求
    required_aspect_ratio = Column(String(20), nullable=True)  # 要求宽高比

    # 变换信息
    transform_x = Column(Float, default=0.0)                # X位置
    transform_y = Column(Float, default=0.0)                # Y位置
    transform_scale_x = Column(Float, default=1.0)          # X缩放
    transform_scale_y = Column(Float, default=1.0)          # Y缩放
    transform_rotation = Column(Float, default=0.0)         # 旋转角度

    # 特效信息
    effects = Column(JSONField, nullable=True)              # 特效列表
    effects_count = Column(Integer, default=0)              # 特效数量

    # 素材属性要求
    material_requirements = Column(JSONField, nullable=True) # 素材要求

    # 优先级和权重
    priority = Column(Integer, default=0)                   # 优先级
    weight = Column(Float, default=1.0)                     # 权重

    # 是否必需
    is_required = Column(Boolean, default=True)             # 是否必需
    is_replaceable = Column(Boolean, default=True)          # 是否可替换

    # 关联关系
    output_materials = relationship("ProductOutputMaterial", back_populates="template_video")

    # 索引
    __table_args__ = (
        Index('idx_template_video_template_segment', 'template_id', 'segment_index'),
        Index('idx_template_video_track', 'track_index', 'track_type'),
        Index('idx_template_video_time', 'start_time', 'end_time'),
        Index('idx_template_video_required', 'is_required', 'is_replaceable'),
    )

    def to_dict(self) -> Dict[str, Any]:
        """转换为字典格式"""
        result = super().to_dict()
        result['effects'] = self.get_effects()
        result['material_requirements'] = self.get_material_requirements()
        return result

    def get_effects(self) -> List[Dict[str, Any]]:
        """获取特效列表"""
        if self.effects:
            return json.loads(self.effects) if isinstance(self.effects, str) else self.effects
        return []

    def get_material_requirements(self) -> Dict[str, Any]:
        """获取素材要求"""
        if self.material_requirements:
            return json.loads(self.material_requirements) if isinstance(self.material_requirements, str) else self.material_requirements
        return {}

    def set_effects(self, effects: List[Dict[str, Any]]):
        """设置特效列表"""
        self.effects = json.dumps(effects, ensure_ascii=False)
        self.effects_count = len(effects)

    def set_material_requirements(self, requirements: Dict[str, Any]):
        """设置素材要求"""
        self.material_requirements = json.dumps(requirements, ensure_ascii=False)

    def get_required_resolution(self) -> Optional[str]:
        """获取要求的分辨率"""
        if self.required_width and self.required_height:
            return f"{self.required_width}x{self.required_height}"
        return None

    def get_transform_info(self) -> Dict[str, float]:
        """获取变换信息"""
        return {
            "x": self.transform_x,
            "y": self.transform_y,
            "scale_x": self.transform_scale_x,
            "scale_y": self.transform_scale_y,
            "rotation": self.transform_rotation
        }

    def is_suitable_for_material(self, material_width: int, material_height: int, material_duration: float) -> bool:
        """判断素材是否适合此片段"""
        # 检查分辨率要求
        if self.required_width and self.required_height:
            if material_width < self.required_width or material_height < self.required_height:
                return False

        # 检查时长要求
        if self.required_duration_min and material_duration < self.required_duration_min:
            return False
        if self.required_duration_max and material_duration > self.required_duration_max:
            return False

        # 检查宽高比要求
        if self.required_aspect_ratio:
            material_ratio = material_width / material_height if material_height > 0 else 0
            # 这里可以添加宽高比匹配逻辑

        return True

    def __repr__(self):
        return f"<TemplateVideo(id={self.id}, template_id={self.template_id}, segment_id='{self.segment_id}', duration={self.duration})>"
